package br.com.sgi.autentication;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;

import br.com.sgi.model.Acesso;
import br.com.sgi.model.Authority;
import br.com.sgi.model.Igreja;
import br.com.sgi.model.Sistema;
import br.com.sgi.model.Users;
import br.com.sgi.service.AcessoService;
import br.com.sgi.service.AuthorityService;
import br.com.sgi.util.Constante;

@Controller("usuarioLogado")
@Scope("session")
public class UsuarioLogado{
	
	private static Authentication usuarioAuthentication;
	
	@Autowired
	private AuthorityService authorityService;
	
	private static Long coSistema;
	
	private static boolean adminGeral;
	private boolean adminLocal;
	private boolean adminRegional;
	private boolean usuarioLocal;
	private boolean adminRegionalGeral;
	
	private boolean exibirMembro;
	private boolean exibirFuncao;
	private boolean exibirIgreja;
	private boolean exibirRelatorio;
	private boolean exibirVisitante;
	private boolean exibirEmail;
	private boolean exibirUser;
	private boolean exibirAcesso;
	private boolean exibirAgenda;
	
	private static String perfil;
	
	private static String ROLE_USUARIO_LOCAL = "ROLE_USUARIO_LOCAL";
	private static String ROLE_ADMIN_REGIONAL= "ROLE_ADMIN_REGIONAL";
	private static String ROLE_ADMIN_LOCAL= "ROLE_ADMIN_LOCAL";
	private static String ROLE_ADMIN_GERAL= "ROLE_ADMIN_GERAL";
	private static String ROLE_ADMIN_SISTEMA= "ROLE_ADMIN_SISTEMA";
	
	private static String codigoPerfil;
	
	private boolean usuario;
	private static Set<String> roles = new HashSet<String>();
	
	private Acesso acesso;
	Authority authority;
	
	private String funcionalidade;
	
	public UsuarioLogado(){
		init();
	}
	
	private Users getUsuarioSistema ()
	{
		return ( Users )SecurityContextHolder.getContext().getAuthentication().getPrincipal();
	}
	
	public static void init() {
		usuarioAuthentication = SecurityContextHolder.getContext().getAuthentication();
		roles = new HashSet<String>();
		for (GrantedAuthority authority : usuarioAuthentication.getAuthorities()) {
			roles.add(authority.getAuthority());
			perfil = authority.getAuthority();
			codigoPerfil = authority.getAuthority();
		}
		
	}

	public static Long getCoSistema() {
		coSistema = coSistemaUsuarioLogado();
		return coSistema;
	}
	
	private static Long coSistemaUsuarioLogado(){
//		if(getUsuarioLogado().getSistema() == null)
		return getUsuarioLogado().getSistema().getCoSeqSistema();
	}

	public static Sistema getSistemaIgreja(){
		
		return getUsuarioLogado().getSistema();
	}
	
	
	public static String getCoUsuario(){
		return getUsuarioLogado().getUsername();
	}
	
	/**
	 * cria a lista com os codigos das igrejas
	 * @param listaCodigos
	 * @return
	 */
	private static String codigoIgrejas(Set<String> listaCodigos){
		StringBuffer codigos = new StringBuffer();
		for(String codigo: listaCodigos){
			if(codigos.length() == 0)
				codigos.append(Long.valueOf(codigo));
			else{
				codigos.append(",");
				codigos.append(Long.valueOf(codigo));
			}
		}
		
		return codigos.toString(); 
	}
	
	
	public static boolean isAdminGeral(){
		init();
		adminGeral = has(ROLE_ADMIN_GERAL);;
		return adminGeral;
	}
	
	public boolean isAdminLocal(){
		init();
		adminLocal = has(ROLE_ADMIN_LOCAL);
		return adminLocal;
	}
	
	public boolean isAdminRegional(){
		init();
		adminRegional = has(ROLE_ADMIN_REGIONAL);
		return adminRegional;
	}

	public boolean isUsuarioLocal() {
		init();
		usuarioLocal = has(ROLE_USUARIO_LOCAL);
		return usuarioLocal;
	}

	

	public Users getUsuarioAuthentication() {
		if(usuarioAuthentication.getPrincipal().equals("anonymousUser"))
			return new Users();
		
		return (Users)usuarioAuthentication.getPrincipal();
	}
	
	public static Users getUsuarioLogado(){
		return ( Users )SecurityContextHolder.getContext().getAuthentication().getPrincipal();
	}
	
	public static Long getCoIgrejaLocal(){
		return getUsuarioLogado().getIgreja()!= null?getUsuarioLogado().getIgreja().getCoSeqIgreja():null;
	}
	
	public static Igreja getIgrejaPertence(){
		return getUsuarioLogado().getIgreja()!= null?getUsuarioLogado().getIgreja():new Igreja();
	}
	
	public static String getEmailIgrejaPertence(){
		return getUsuarioLogado().getIgreja()!= null?getUsuarioLogado().getIgreja().getEmail():"";
	}
	
	public static String getUsernameUsuarioLogado(){
		return getUsuarioLogado().getUsername();
	}
	
	public boolean isUsuario() {
		return usuario;
	}

	public void setUsuario(boolean usuario) {
		this.usuario = usuario;
	}

	public static Set<String> getRoles( )
	{
		return roles;
	}
	
	public static boolean has ( String role )
	{
		return getRoles( ).contains( role );
	}

	public String getPerfil() {
		init();
		perfil =  authorityService.buscarDescricaoPorAuthoriby(perfil);
		return perfil;
	}

	public void setPerfil(String perfil) {
		this.perfil = perfil;
	}

	public void setUsuarioLocal(boolean usuarioLocal) {
		this.usuarioLocal = usuarioLocal;
	}

	public boolean isAdminRegionalGeral() {
		if(has(ROLE_ADMIN_REGIONAL) || has(ROLE_ADMIN_GERAL))
			adminRegionalGeral = true;
		else
			adminRegionalGeral = false;
		
		return adminRegionalGeral;
	}

	public void setAdminRegionalGeral(boolean adminRegionalGeral) {
		this.adminRegionalGeral = adminRegionalGeral;
	}
	
	
	
	public Acesso getAcesso() {
		if(codigoPerfil.equals(ROLE_ADMIN_SISTEMA)){
			acesso =  new Acesso(true, true, true, true, true);
			exibirEmail = exibirFuncao = exibirIgreja = exibirMembro = exibirRelatorio = exibirUser = exibirVisitante =  exibirAcesso = true;
		}
		else
			if(acesso == null){
				acesso = obterAcesso(funcionalidade);
			}
		return acesso;
	}
	
	/**
	 * busca os as permissoes concedidas a cada funcionalidade para cada perfil
	 * @param funcionalidade
	 * @return
	 */
	private Acesso obterAcesso(String funcionalidade){
		Acesso acesso = null;
		if(authority == null)
			authority = authorityService.buscarAuthorityPorNome(codigoPerfil);
		
		if(codigoPerfil.equals(ROLE_ADMIN_SISTEMA)){
			acesso =  new Acesso(true, true, true, true, true);
		}else
			{
				acesso = bucaAcessoPorFuncionalidade(funcionalidade, authority);//acessoService.buscarAcessoPorPerfil(codigoPerfil, funcionalidade);
				if(acesso == null)
					acesso = acesso != null? acesso:new Acesso(false, false, false, false, false) ;
			}
		return acesso;
	}
	
	/**
	 * retorna os acesso vinculados ao perfil do usario
	 * @param funcionalidade
	 * @param autho
	 * @return
	 */
	private Acesso bucaAcessoPorFuncionalidade(String funcionalidade, Authority autho){
		Acesso acesso = null;
		
		List<Acesso> listAcessos = autho.getAcessos();
		for(Acesso ac: listAcessos){
			if(ac.getFuncionalidade().getNome().equals(funcionalidade)){
				acesso = ac;
				break;
			}
		}
		
		return acesso;
	}

	public void setAcesso(Acesso acesso) {
		this.acesso = acesso;
	}

	public boolean isExibirNoMenu() {
		return getAcesso().getExibirNoMenu()!=null?getAcesso().getExibirNoMenu():true;
	}


	public boolean isExibirEditar() {
		return getAcesso().getExibirEditar()!=null?getAcesso().getExibirEditar():true;
	}


	public boolean isExibirSalvar() {
		return getAcesso().getExibirSalvar()!=null?getAcesso().getExibirSalvar():true;
	}


	public boolean isExibirNovo() {
		return getAcesso().getExibirNovo()!=null?getAcesso().getExibirNovo():true;
	}


	public boolean isExibirExcluir() {
		return getAcesso().getExibirExcluir()!=null?getAcesso().getExibirExcluir():true;
	}


	public String getFuncionalidade() {
		return funcionalidade;
	}

	public void setFuncionalidade(String funcionalidade) {
		this.funcionalidade = funcionalidade;
	}

	public boolean isExibirMembro() {
		exibirMembro = obterAcesso(Constante.FUNC_MEMBRO).getExibirNoMenu();
		return exibirMembro;
	}

	public void setExibirMembro(boolean exibirMembro) {
		this.exibirMembro = exibirMembro;
	}

	public boolean isExibirFuncao() {
		exibirFuncao = obterAcesso(Constante.FUNC_FUNCAO).getExibirNoMenu();
		return exibirFuncao;
	}

	public void setExibirFuncao(boolean exibirFuncao) {
		this.exibirFuncao = exibirFuncao;
	}

	public boolean isExibirIgreja() {
		exibirIgreja = obterAcesso(Constante.FUNC_IGREJA).getExibirNoMenu();
		return exibirIgreja;
	}

	public void setExibirIgreja(boolean exibirIgreja) {
		this.exibirIgreja = exibirIgreja;
	}

	public boolean isExibirRelatorio() {
		exibirRelatorio = obterAcesso(Constante.FUNC_RELATORIO).getExibirNoMenu();
		return exibirRelatorio;
	}

	public void setExibirRelatorio(boolean exibirRelatorio) {
		this.exibirRelatorio = exibirRelatorio;
	}

	public boolean isExibirVisitante() {
		exibirVisitante = obterAcesso(Constante.FUNC_VISITANTE).getExibirNoMenu();
		return exibirVisitante;
	}

	public void setExibirVisitante(boolean exibirVisitante) {
		this.exibirVisitante = exibirVisitante;
	}

	public boolean isExibirEmail() {
		exibirEmail = obterAcesso(Constante.FUNC_EMAIL).getExibirNoMenu();
		return exibirEmail;
	}

	public void setExibirEmail(boolean exibirEmail) {
		this.exibirEmail = exibirEmail;
	}

	public boolean isExibirUser() {
		exibirUser = obterAcesso(Constante.FUNC_USER).getExibirNoMenu();
		return exibirUser;
	}

	public void setExibirUser(boolean exibirUser) {
		this.exibirUser = exibirUser;
	}

	public boolean isExibirAcesso() {
		exibirAcesso = obterAcesso(Constante.FUNC_ACESSO).getExibirNoMenu();
		return exibirAcesso;
	}

	public void setExibirAcesso(boolean exibirAcesso) {
		this.exibirAcesso = exibirAcesso;
	}

	/**
	 * @return the exibirAgenda
	 */
	public boolean isExibirAgenda() {
		exibirAgenda = obterAcesso(Constante.FUNC_AGENDA).getExibirNoMenu();
		return exibirAgenda;
	}

	/**
	 * @param exibirAgenda the exibirAgenda to set
	 */
	public void setExibirAgenda(boolean exibirAgenda) {
		this.exibirAgenda = exibirAgenda;
	}
	
	
	
	
	
}